package com.zzyl.nursing.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.DeviceShadowData;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceShadowRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceShadowResponse;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.domain.FamilyMember;
import com.zzyl.nursing.domain.member.FamilyMemberElder;
import com.zzyl.nursing.dto.member.MemberUserAddDto;
import com.zzyl.nursing.dto.member.QueryDeviceDataListByDay;
import com.zzyl.nursing.dto.member.QueryDeviceDataListByWeek;
import com.zzyl.nursing.dto.member.QueryDevicePropertyStatus;
import com.zzyl.nursing.mapper.FamilyMemberMapper;
import com.zzyl.nursing.mapper.MemberUserMapper;
import com.zzyl.nursing.service.IDeviceDataService;
import com.zzyl.nursing.service.MemberUserService;
import com.zzyl.nursing.vo.member.MemberInfo;
import com.zzyl.nursing.vo.member.MemberUserMy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 *TODO
 *@Author zhu
 *@Date 2025/10/29 16:33
 */
@Service
public class MemberUserServiceImpl extends ServiceImpl<MemberUserMapper, FamilyMemberElder> implements MemberUserService {
    @Autowired
    private MemberUserMapper memberUserMapper;
    @Autowired
    private ElderServiceImpl elderService;
    @Autowired
    private FamilyMemberMapper familyMemberMapper;
    @Autowired
    private DeviceServiceImpl deviceService;
    @Autowired
    private IoTDAClient client;
    @Autowired
    private IDeviceDataService dataService;

    /**
     * 绑定家人
     *
     * @param dto
     */
    @Override
    public void add(MemberUserAddDto dto) {
        // 身份验证：根据身份证号和姓名查询老人信息
        List<Elder> elderList = elderService.lambdaQuery()
                .eq(Elder::getIdCardNo, dto.getIdCard())
                .eq(Elder::getName, dto.getName())
                .list();

        // 获取当前登录的家庭成员
        Long currentFamilyMemberId = UserThreadLocal.getUserId();
        FamilyMember currentFamilyMember = familyMemberMapper.selectById(currentFamilyMemberId);

        // 如果老人存在，并且当前家庭成员也存在，则进行绑定操作
        if (CollUtil.isNotEmpty(elderList) && currentFamilyMember != null) {
            for (Elder elder : elderList) {
                FamilyMemberElder familyMemberElder = new FamilyMemberElder();
                familyMemberElder.setElderId(elder.getId());
                familyMemberElder.setCreateBy(currentFamilyMemberId);
                familyMemberElder.setUpdateBy(currentFamilyMemberId);
                familyMemberElder.setFamilyMemberId(currentFamilyMember.getId());
                familyMemberElder.setRemark(dto.getRemark());// 设置称呼等其他字段
                this.save(familyMemberElder);
            }

        }
    }

    /**
     * 查询家人列表
     *
     * @return
     */
    @Override
    public List<MemberUserMy> my() {
        //根据当前登录用户id查询表
        List<FamilyMemberElder> familyMemberElderList = this.lambdaQuery()
                .eq(FamilyMemberElder::getFamilyMemberId, UserThreadLocal.getUserId())
                .list();
        //根据老人id取出老人名字并封装，返回；
        List<MemberUserMy> collect = familyMemberElderList.stream().map(x -> {
            Elder elder = elderService.selectElderById(x.getElderId());
            MemberUserMy bean = BeanUtil.toBean(x, MemberUserMy.class);
            bean.setElderName(elder.getName());
            return bean;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 分页查询
     *
     * @return
     */
    @Override
    public List<MemberInfo> listpage() {
        Long userId = UserThreadLocal.getUserId();
        return memberUserMapper.listpage(userId);
    }

    /**
     * 查询健康数据
     *
     * @param
     */
    @Override
    public Map<String, Object> QueryDevicePropertyStatus(QueryDevicePropertyStatus dto) {
        // 从数据库查询设备信息
        Device device = deviceService.lambdaQuery()
                .eq(Device::getProductKey, dto.getProductKey())
                .eq(Device::getDeviceName, dto.getDeviceName())
                .one();
        if (device == null) {
            throw new BaseException("表中设备不存在");
        }

        // 调用 IoT 平台接口获取设备影子
        ShowDeviceShadowRequest showDeviceShadowRequest = new ShowDeviceShadowRequest();
        showDeviceShadowRequest.withDeviceId(device.getIotId());
        ShowDeviceShadowResponse response;
        try {
            response = client.showDeviceShadow(showDeviceShadowRequest);
        } catch (Exception e) {
            throw new BaseException("调用IOT平台失败: " + e.getMessage());
        }

        if (response.getHttpStatusCode() != 200) {
            throw new BaseException("设备未上报数据或无影子信息");
        }

        List<DeviceShadowData> shadowDataList = response.getShadow();
        if (CollUtil.isEmpty(shadowDataList)) {
            Map<String, Object> emptyList = new HashMap<>();
            emptyList.put("propertyStatusInfo", new ArrayList<>());
            return Collections.singletonMap("list", emptyList);
        }

        String eventTime = shadowDataList.get(0).getReported().getEventTime();
        long timestamp = LocalDateTime.parse(eventTime, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'"))
                .atZone(ZoneOffset.UTC)
                .toInstant()
                .toEpochMilli();

        if (StrUtil.isBlank(eventTime)) {
            Map<String, Object> emptyList = new HashMap<>();
            emptyList.put("propertyStatusInfo", new ArrayList<>());
            return Collections.singletonMap("list", emptyList);
        }

        LocalDateTime reportTime;
        try {
            reportTime = OffsetDateTime.parse(eventTime, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmssX"))
                    .atZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                    .toLocalDateTime();
        } catch (Exception e) {
            throw new BaseException("时间解析失败: " + eventTime);
        }

        // 解析属性
        JSONObject propertiesJSONObject = JSONUtil.parseObj(shadowDataList.get(0).getReported().getProperties());
        if (propertiesJSONObject == null || propertiesJSONObject.isEmpty()) {
            Map<String, Object> emptyList = new HashMap<>();
            emptyList.put("propertyStatusInfo", new ArrayList<>());
            return Collections.singletonMap("list", emptyList);
        }

        // 分离 heartRate 和其他属性
        Map<String, Object> heartRateProperty = null;
        List<Map<String, Object>> otherProperties = new ArrayList<>();

        for (Map.Entry<String, Object> entry : propertiesJSONObject.entrySet()) {
            String propertyName = entry.getKey();
            Object propertyValue = entry.getValue();

            Map<String, Object> propertyMap = new HashMap<>();
            propertyMap.put("identifier", propertyName);
            propertyMap.put("time", timestamp);

            if ("heartRate".equalsIgnoreCase(propertyName)) {
                // 心率特殊处理：转为 Double 后四舍五入取整
                try {
                    Double heartRateValue = Double.valueOf(propertyValue.toString());
                    Integer roundedHeartRate = (int) Math.round(heartRateValue);
                    propertyMap.put("value", roundedHeartRate);
                } catch (Exception e) {
                    // 如果转换失败，默认设为 0 或 null
                    propertyMap.put("value", 0);
                }
                heartRateProperty = propertyMap;
            } else {
                propertyMap.put("value", propertyValue);
                otherProperties.add(propertyMap);
            }
        }

        // 对其他属性排序（按名称字母序）
        otherProperties.sort(Comparator.comparing(p -> (String) p.get("identifier")));

        // 构建最终列表：先其他属性，后 heartRate
        List<Map<String, Object>> propertyStatusInfoList = new ArrayList<>(otherProperties);
        if (heartRateProperty != null) {
            propertyStatusInfoList.add(heartRateProperty);
        }

        // 封装到 list 对象中
        Map<String, Object> listMap = new HashMap<>();
        listMap.put("propertyStatusInfo", propertyStatusInfoList);

        // 返回最终结果
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("list", listMap);
        return resultMap;
    }

    /**
     * 按天统计指标
     * @param query
     * @return
     */
    @Override
    public List<Map<String, Object>> queryDeviceDataListByDay(QueryDeviceDataListByDay query) {
        // 解析毫秒时间戳为 LocalDateTime
        LocalDateTime startTime = Instant.ofEpochMilli(Long.parseLong(query.getStartTime())).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();
        LocalDateTime endTime = Instant.ofEpochMilli(Long.parseLong(query.getEndTime())).atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();

        // 查询数据库
        List<Map<String, Object>> rawList = memberUserMapper.queryDeviceDataListByDay(
                query.getIotId(),
                query.getFunctionId(),
                startTime,
                endTime
        );

        // 构造完整的小时列表（补全缺失）
        List<Map<String, Object>> result = new ArrayList<>();

        // 获取起始时间和结束时间的小时数
        LocalTime startHour = startTime.toLocalTime();
        LocalTime endHour = endTime.toLocalTime();

        // 补全从 startHour 到 endHour 的每一小时
        for (int hour = startHour.getHour(); hour <= endHour.getHour(); hour++) {
            Map<String, Object> item = new HashMap<>();
            item.put("dateTime", String.format("%02d:00", hour));
            item.put("dataValue", 0.0);

            // 查找是否有对应小时的数据
            int finalHour = hour;
            Optional<Map<String, Object>> found = rawList.stream()
                    .filter(m -> m.get("dateTime").equals(String.format("%02d:00", finalHour)))
                    .findFirst();

            if (found.isPresent()) {
                item.put("dataValue", found.get().get("dataValue"));
            }

            result.add(item);
        }

        return result;
    }

    /**
     * 按周统计指标
     *
     * @param quary
     * @return
     */
    @Override
    public List<Map<String, Object>> queryDeviceDataListByWeek(QueryDeviceDataListByWeek quary) {
        // 解析毫秒时间戳为 LocalDateTime
        LocalDateTime startTime = Instant.ofEpochMilli(Long.parseLong(quary.getStartTime()))
                .atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();
        LocalDateTime endTime = Instant.ofEpochMilli(Long.parseLong(quary.getEndTime()))
                .atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime();

        // 查询数据库
        List<Map<String, Object>> rawList = memberUserMapper.queryDeviceDataListByWeek(
                quary.getIotId(),
                quary.getFunctionId(),
                startTime,
                endTime
        );

        // 构造完整的天数列表（补全缺失）
        List<Map<String, Object>> result = new ArrayList<>();

        // 获取起始和结束的日期（LocalDate）
        LocalDate startDay = startTime.toLocalDate();
        LocalDate endDay = endTime.toLocalDate();

        // 使用 LocalDate 迭代每一天
        for (LocalDate date = startDay; !date.isAfter(endDay); date = date.plusDays(1)) {
            // 格式化为 MM.dd
            String formattedDate = String.format("%02d.%02d", date.getMonthValue(), date.getDayOfMonth());

            Map<String, Object> item = new HashMap<>();
            item.put("dateTime", formattedDate);
            item.put("dataValue", 0.0); // 默认值为 0

            // 查找 rawList 中是否有这一天的数据
            Optional<Map<String, Object>> found = rawList.stream()
                    .filter(m -> formattedDate.equals(m.get("dateTime")))
                    .findFirst();

            if (found.isPresent()) {
                item.put("dataValue", found.get().get("dataValue"));
            }

            result.add(item);
        }

        return result;
    }

    /**
     * 解绑老人
     *
     * @param id
     */
    @Override
    public void deletebyid(Integer id) {
       memberUserMapper.deletebyid(id);
    }

}